package com.asder.tool.generator.main;


import com.asder.tool.generator.mybatisplus.DriverName;
import com.asder.tool.generator.mybatisplus.Generator;
import com.asder.tool.generator.utils.DatabaseUtil;
import com.asder.tool.generator.utils.MyPrintStream;
import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;
import com.google.common.base.Preconditions;
import org.apache.commons.lang.StringUtils;

import javax.swing.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.sql.*;
import java.util.*;

/**
 * Hello world!
 *
 */
public class App
{

    private static List convertList(ResultSet rs) throws SQLException{
        List list = new ArrayList();
        ResultSetMetaData md = rs.getMetaData();//获取键名
        int columnCount = md.getColumnCount();//获取行的数量
        while (rs.next()) {
            Map rowData = new HashMap();//声明Map
            for (int i = 1; i <= columnCount; i++) {
                rowData.put(md.getColumnName(i), rs.getObject(i));//获取键名及值
            }
            list.add(rowData);
        }
        return list;
    }




	// 用以检验当前输入数据源类型是否支持
	@SuppressWarnings("serial")
	private static Set<String> dbSourceTypeSet = new HashSet<String>(){{

		for(DbType type : DbType.values()) {
			add(type.getDb());
		}
	}};
	
	// 用以检验当前输入JDBC驱动名称是否支持
	@SuppressWarnings("serial")
	private static Set<String> driverNameTypeSet = new HashSet<String>(){{

		for(DriverName type : DriverName.values()) {
			add(type.getValue());
		}
	}};
	
	public static void main(String[] args) {
		
//		if(args.length == 0) {
//
			// 图形界面模式
			guiMode();
//		} else {
//
//			// 命令行模式
//			consoleMode(args);
//		}
	}
	
    private static void exec(String outputDir, String author, String dbType, String driverName, String url,
                             String username, String password, NamingStrategy naming, String includeTablename,String parentPackage,String moduleName) throws Exception {
    	
    	System.out.println("=== Processing... ===");

		// 执行

    	Generator.run(outputDir, author, Enum.valueOf(DbType.class, dbType.trim().toUpperCase()),
    									 driverName, url, username, password, naming, includeTablename,parentPackage,moduleName);

		System.out.println("=== Execution Successful! ===");
    }
	
	public static void consoleMode(String[] args) {
		
		// 输入参数校验
		Preconditions.checkArgument(args.length == 9 || args.length == 8, "Usage -> MybatisPlusGeneratorTool.jar outputDir, author, dbType, driverName, url, username, password, naming, includeTablename "
				+ "-> F://temp user mysql com.mysql.jdbc.Driver jdbc:mysql://192.168.31.115:3306/vcloud?useUnicode=true&amp;characterEncoding=UTF-8&amp;generateSimpleParameterMetadata=true root admin123 underline_to_camel vcloud_device");

		String outputDir = args[0];
		String author = args[0];
		String dbType = args[0];
		String driverName = args[0];
		String url = args[0];
		String username = args[0];
		String password = args[0];
		String naming = args[0];
		String includeTablename = args[0];
        String parentPackage=args[0];
        String moduleName=args[0];
		Preconditions.checkArgument(dbSourceTypeSet.contains(dbType), "dbSourceTypeSet is not supported! Usage -> [mysql, oracle, sql_server, postgre_sql]");
		Preconditions.checkArgument(driverNameTypeSet.contains(driverName), "driverNameTypeSet is not supported! Usage -> [com.mysql.jdbc.Driver, oracle.jdbc.driver.OracleDriver, com.microsoft.jdbc.sqlserver.SQLServerDriver, org.postgresql.Driver]");
		
		try {

			// 执行
			exec(outputDir, author, dbType, driverName, url,
				 username, password, Enum.valueOf(NamingStrategy.class, naming.trim().toUpperCase()), includeTablename,parentPackage,moduleName);
		} catch (Exception e) {
			
			e.printStackTrace();
		}
	}
	
	public static void guiMode() {
		
        // 创建 JFrame 实例
        JFrame frame = new JFrame("Mybatis Plus 代码生成器");
        frame.setSize(1000, 800);
        frame.setLocationRelativeTo(null);//窗体居中显示

        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        JPanel panel = new JPanel();    
        // 添加面板
        frame.add(panel);
        
        // 调用用户定义的方法并添加组件到面板
        placeComponents(panel);

        // 设置界面可见
        frame.setVisible(true);

	}
	
	static int interval = 20;
	static int count = 0;
	private static int getInterval() {
		
		if(2 == count++) {
			interval += 30;
			count = 1;
		}
		
		return interval;
	}
	
    private static void placeComponents(JPanel panel) {
    	
        /* 
         * 这边设置布局为 null
         */
        panel.setLayout(null);

        // 创建 JLabel      
        JLabel outputDirLabel = new JLabel("输出路径:");
        outputDirLabel.setBounds(10,getInterval(),80,25);
        panel.add(outputDirLabel);


        final JTextField outputDirText = new JTextField(20);
        outputDirText.setBounds(100,getInterval(),265,25);
        panel.add(outputDirText);
        outputDirText.setEnabled(false);
        outputDirText.setText("D://temp");

        // 创建按钮
        JButton openfile = new JButton("选择文件路径");
        openfile.setBounds(380, 20, 80, 25);
        panel.add(openfile);
        openfile.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
               JFileChooser jf = new JFileChooser();
                jf.setSize(900,900);
                jf.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);//只能选择目录
                jf.setCurrentDirectory(new File("D:"));
                int i=jf.showOpenDialog(null);//显示打开的文件对话框
                if(i== jf.APPROVE_OPTION){ //打开文件
                    String path = jf.getSelectedFile().getAbsolutePath();
                    outputDirText.setText(path);
                }

            }
        });


        JLabel authorLabel = new JLabel("作者:");
        authorLabel.setBounds(10,getInterval(),80,25);
        panel.add(authorLabel);



        final JTextField authorText = new JTextField(20);
        authorText.setBounds(100,getInterval(),265,25);
        panel.add(authorText);
        authorText.setText("zy");

        JLabel parentLabel = new JLabel("包名:");
        parentLabel.setBounds(10,getInterval(),80,25);
        panel.add(parentLabel);

        final JTextField parentText = new JTextField(20);
        parentText.setBounds(100,getInterval(),265,25);
        panel.add(parentText);
        parentText.setText("com.xd.out");


        JLabel moduleLabel = new JLabel("模块名:");
        moduleLabel.setBounds(10,getInterval(),80,25);
        panel.add(moduleLabel);

        final JTextField moduleText = new JTextField(20);
        moduleText.setBounds(100,getInterval(),265,25);
        panel.add(moduleText);
        moduleText.setText("base");

        JLabel dbTypeLabel = new JLabel("数据源类型:");
        dbTypeLabel.setBounds(10,getInterval(),80,25);
        panel.add(dbTypeLabel);

        final JComboBox<?> dbTypeCombo = new JComboBox<Object>(dbSourceTypeSet.toArray());
        dbTypeCombo.setBounds(100,getInterval(),165,25);
        panel.add(dbTypeCombo);

        
        JLabel driverTypeLabel = new JLabel("JDBC驱动:");
        driverTypeLabel.setBounds(10,getInterval(),80,25);
        panel.add(driverTypeLabel);

        final JComboBox<?> driverNameCombo = new JComboBox<Object>(driverNameTypeSet.toArray());
        driverNameCombo.setBounds(100,getInterval(),165,25);
        panel.add(driverNameCombo);

        
        JLabel urlLabel = new JLabel("URL:");
        urlLabel.setBounds(10,getInterval(),80,25);
        panel.add(urlLabel);

        final JTextField urlText = new JTextField(20);
        urlText.setBounds(100,getInterval(),800,25);
        panel.add(urlText);
        urlText.setText("jdbc:mysql://192.168.1.253:3306/xdtrade?serverTimezone=UTC&useUnicode=true&characterEncoding=utf8");
        
        JLabel usernameLabel = new JLabel("用户名:");
        usernameLabel.setBounds(10,getInterval(),80,25);
        panel.add(usernameLabel);

        final JTextField usernameText = new JTextField(20);
        usernameText.setBounds(100,getInterval(),165,25);
        panel.add(usernameText);
        usernameText.setText("root");
        
        JLabel passwordLabel = new JLabel("密码:");
        passwordLabel.setBounds(10,getInterval(),80,25);
        panel.add(passwordLabel);

        final JTextField passwordText = new JTextField(20);
        passwordText.setBounds(100,getInterval(),165,25);
        panel.add(passwordText);
        passwordText.setText("admin");
        
        JLabel policyLabel = new JLabel("表名生成策略:");
        policyLabel.setBounds(10,getInterval(),110,25);
        panel.add(policyLabel);
        
        NamingStrategy[] namingItem = {NamingStrategy.nochange, NamingStrategy.underline_to_camel};
        final JComboBox<?> namingCombo = new JComboBox<Object>(namingItem);
        namingCombo.setBounds(100,getInterval(),165,25);
        panel.add(namingCombo);
        namingCombo.setSelectedIndex(1);
        
        JLabel includetablenameLabel = new JLabel("包含表名:");
        includetablenameLabel.setBounds(10,getInterval(),80,25);
        panel.add(includetablenameLabel);

        final JTextField includeTablenameText = new JTextField();
        includeTablenameText.setBounds(100,getInterval(),800,25);
        panel.add(includeTablenameText);
        includeTablenameText.setText("");

        // 创建按钮
        JButton button = new JButton("生成");
        button.setBounds(10, getInterval(), 80, 25);
        panel.add(button);
        button.addActionListener(new ActionListener() { 

            @Override 
            public void actionPerformed(ActionEvent e) {

        		String outputDir = outputDirText.getText();
        		String author = authorText.getText();
        		String dbType = dbTypeCombo.getSelectedItem().toString();
        		String driverName = driverNameCombo.getSelectedItem().toString();
        		String url = urlText.getText();
        		String username = usernameText.getText();
        		String password = passwordText.getText();
        		NamingStrategy naming = (NamingStrategy)namingCombo.getSelectedItem();
        		String includeTablename = includeTablenameText.getText();
        		String parentPackge=parentText.getText();
                String moduleName=moduleText.getText();
        		try {
        			
					exec(outputDir, author, dbType, driverName, url,
						 username, password, naming, includeTablename,parentPackge,moduleName);


				} catch (Exception ex) {
					
					ex.printStackTrace();
				}
            } 

        });


        // 创建按钮
        JButton testdrive = new JButton("连接测试");
        testdrive.setBounds(100, getInterval(), 160, 25);
        panel.add(testdrive);
        testdrive.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent event) {
                String driverName = driverNameCombo.getSelectedItem().toString();
                String url = urlText.getText();
                String username = usernameText.getText();
                String password = passwordText.getText();
                //加载驱动类
                try {
                    Class.forName(driverName);
                    //Class.forName("com.mysql.jdbc.Driver");
                    Connection conn= DriverManager.getConnection(url,username,password);
                    JOptionPane.showMessageDialog(null, "连接成功", "连接测试", JOptionPane.INFORMATION_MESSAGE);
                    DatabaseMetaData m_DBMetaData = conn.getMetaData();
                    ResultSet tableRet = m_DBMetaData.getTables(conn.getCatalog(), "%","%",new String[]{"TABLE"});
                    List<String> talbelist = DatabaseUtil.getTableNames(conn);
                    System.out.println(StringUtils.join(talbelist.toArray(), ","));
                   conn.close();
                } catch (ClassNotFoundException e) {
                    JOptionPane.showMessageDialog(null, "连接失败，驱动类找不到", "连接测试", JOptionPane.ERROR_MESSAGE);
                return;
                }

                catch (SQLException e) {
                   if(e instanceof  com.mysql.cj.jdbc.exceptions.ConnectionFeatureNotAvailableException)
                      JOptionPane.showMessageDialog(null, "连接失败，数据库不存在", "连接测试", JOptionPane.ERROR_MESSAGE);
                  else{
                      e.printStackTrace();
                       JOptionPane.showMessageDialog(null, "连接失败,请检查用户名密码", "连接测试", JOptionPane.ERROR_MESSAGE);
                   }

                    return;
                } catch (Exception e) {
                    e.printStackTrace();
                }


            }
        });

        JTextArea consoleArea = new JTextArea();
		consoleArea.setWrapStyleWord(true); // 激活断行不断字功能
		
		JScrollPane jscrollPane = new JScrollPane(consoleArea);
		jscrollPane.setBounds(0, interval+30, 1000, 600);
		panel.add(jscrollPane);

        MyPrintStream mps = new MyPrintStream(System.out, consoleArea);
        System.setOut(mps);  
        System.setErr(mps);
    }



}
